﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using Windows.ApplicationModel.Resources.Core;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Imaging;
using System.Xml.Linq;
using System.IO;
using System.Threading.Tasks;

// The data model defined by this file serves as a representative example of a strongly-typed
// model that supports notification when members are added, removed, or modified.  The property
// names chosen coincide with data bindings in the standard item templates.
//
// Applications may use this model as a starting point and build on it, or discard it entirely and
// replace it with something appropriate to their needs.

namespace SharepointCompanion.Data
{
    /// <summary>
    /// Base class for <see cref="SharepointDataItem"/> and <see cref="SharepointDataGroup"/> that
    /// defines properties common to both.
    /// </summary>
    [Windows.Foundation.Metadata.WebHostHidden]
    public abstract class SharepointDataCommon : SharepointCompanion.Common.BindableBase
    {
        //private static Uri _baseUri = new Uri("ms-appx:///");

        public SharepointDataCommon(String uniqueId, String title)//, String subtitle, String imagePath, String description)
        {
            this._uniqueId = uniqueId;
            this._title = title;
            //this._subtitle = subtitle;
            //this._description = description;
            //this._imagePath = imagePath;
        }

        private string _uniqueId = string.Empty;
        public string UniqueId
        {
            get { return this._uniqueId; }
            set { this.SetProperty(ref this._uniqueId, value); }
        }

        private string _title = string.Empty;
        public string Title
        {
            get { return this._title; }
            set { this.SetProperty(ref this._title, value); }
        }

        //private string _subtitle = string.Empty;
        //public string Subtitle
        //{
        //    get { return this._subtitle; }
        //    set { this.SetProperty(ref this._subtitle, value); }
        //}

        //private string _description = string.Empty;
        //public string Description
        //{
        //    get { return this._description; }
        //    set { this.SetProperty(ref this._description, value); }
        //}

        //private ImageSource _image = null;
        //private String _imagePath = null;
        //public ImageSource Image
        //{
        //    get
        //    {
        //        if (this._image == null && this._imagePath != null)
        //        {
        //            this._image = new BitmapImage(new Uri(SampleDataCommon._baseUri, this._imagePath));
        //        }
        //        return this._image;
        //    }

        //    set
        //    {
        //        this._imagePath = null;
        //        this.SetProperty(ref this._image, value);
        //    }
        //}

        //public void SetImage(String path)
        //{
        //    this._image = null;
        //    this._imagePath = path;
        //    this.OnPropertyChanged("Image");
        //}
    }

    /// <summary>
    /// Generic item data model.
    /// </summary>
    public class SharepointDataItem : SharepointDataCommon
    {
        public SharepointDataItem(String uniqueId, String title, String content, SharepointDataGroup group)
            : base(uniqueId, title)
        {
            this._content = content;
            this._group = group;
        }

        private string _content = string.Empty;
        public string Content
        {
            get { return this._content; }
            set { this.SetProperty(ref this._content, value); }
        }

        private SharepointDataGroup _group;
        public SharepointDataGroup Group
        {
            get { return this._group; }
            set { this.SetProperty(ref this._group, value); }
        }
    }

    /// <summary>
    /// Generic group data model.
    /// </summary>
    public class SharepointDataGroup : SharepointDataCommon
    {
        //public bool Visible
        //{
        //    get { return _items.Count > 0; }
        //}
        public SharepointDataGroup(String uniqueId, String title)
            : base(uniqueId, title)
        {
           // _items.CollectionChanged += (o, e) => OnPropertyChanged("Visible");
        }

        private ObservableCollection<SharepointDataItem> _items = new ObservableCollection<SharepointDataItem>();
        public ObservableCollection<SharepointDataItem> Items
        {
            get { return this._items; }
        }

        public IEnumerable<SharepointDataItem> TopItems
        {
            // Provides a subset of the full items collection to bind to from a GroupedItemsPage
            // for two reasons: GridView will not virtualize large items collections, and it
            // improves the user experience when browsing through groups with large numbers of
            // items.
            //
            // A maximum of 12 items are displayed because it results in filled grid columns
            // whether there are 1, 2, 3, 4, or 6 rows displayed
            get { return this._items.Take(12); }
        }
    }

    /// <summary>
    /// Creates a collection of groups and items with hard-coded content.
    /// </summary>
    public sealed class SharepointDataSource
    {
        private static SharepointDataSource _sharepointDataSource = new SharepointDataSource();

        Sharepoint.Client.SPConnection _connection;
        private ObservableCollection<SharepointDataGroup> _itemGroups = new ObservableCollection<SharepointDataGroup>();
        public ObservableCollection<SharepointDataGroup> AllGroups
        {
            get { return this._itemGroups; }
        }

        public static IEnumerable<SharepointDataGroup> GetGroups(string uniqueId)
        {
            if (!uniqueId.Equals("AllGroups")) throw new ArgumentException("Only 'AllGroups' is supported as a collection of groups");

            return _sharepointDataSource.AllGroups;
        }

        public static SharepointDataGroup GetGroup(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sharepointDataSource.AllGroups.Where((group) => group.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public static SharepointDataItem GetItem(string uniqueId)
        {
            // Simple linear search is acceptable for small data sets
            var matches = _sharepointDataSource.AllGroups.SelectMany(group => group.Items).Where((item) => item.UniqueId.Equals(uniqueId));
            if (matches.Count() == 1) return matches.First();
            return null;
        }

        public SharepointDataSource()
        {
            _itemGroups.Add(new SharepointDataGroup("1", "test group"));
            _itemGroups[0].Items.Add(new SharepointDataItem("1","test 1","this is the content",_itemGroups[0]));
            _itemGroups[0].Items.Add(new SharepointDataItem("2","test 2","this is the content",_itemGroups[0]));
            _itemGroups.Add(new SharepointDataGroup("2", "test group 2"));
            _itemGroups[1].Items.Add(new SharepointDataItem("11", "test 1", "this is the content", _itemGroups[1]));
            _itemGroups[1].Items.Add(new SharepointDataItem("12", "test 2", "this is the content", _itemGroups[1]));

        }
        const string _nsapp = "http://www.w3.org/2007/app";
        const string _nsatom = "http://www.w3.org/2005/Atom";

        public static async Task LoadDataAsync(Sharepoint.Client.SPConnection connection)
        {
            await _sharepointDataSource.loadDataAsync(connection);
        }

        async Task loadDataAsync(Sharepoint.Client.SPConnection connection)
        {
            _itemGroups.Clear();
            try
            {
                _connection = connection;
                //await _connection.SigninAsync(user, pwd);
                var stream = await _connection.RequestAsync();

                var xdocument = XDocument.Load(stream);

                var workspace = xdocument.Descendants(XName.Get("workspace", _nsapp)).FirstOrDefault();
                var title = workspace.Element(XName.Get("title", _nsatom)).Value;
                //group.Title = title;
                var descendats = workspace.Descendants(XName.Get("collection", _nsapp));
                List<SharepointDataGroup> groups = new List<SharepointDataGroup>();
                foreach (var descendant in descendats)
                {
                    var id = descendant.Attribute(XName.Get("href")).Value;
                    var elementTitle = descendant.Element(XName.Get("title", _nsatom)).Value;
                    groups.Add(new SharepointDataGroup(id, elementTitle));
                }

                foreach (var item in groups)
                {
                    try
                    {
                        await loadItemAsync(item);
                    }
                    catch (Exception ex)
                    {
                        //TODO:detect design mode
                        _itemGroups.Add(new SharepointDataGroup(ex.HResult.ToString(), ex.Message));
                        _itemGroups[0].Items.Add(new SharepointDataItem("item 1", "item 1", null, _itemGroups[0]));
                        _itemGroups[0].Items.Add(new SharepointDataItem("item 2", "item 2", null, _itemGroups[0]));
                    }
                }
                //await Task.WhenAll(from item in groups
                //                   select loadItemAsync(item));
            }
            catch (Exception ex)
            {
                //TODO:detect design mode
                _itemGroups.Add(new SharepointDataGroup("id1", "group"));
                _itemGroups[0].Items.Add(new SharepointDataItem("item 1", "item 1", null, _itemGroups[0]));
                _itemGroups[0].Items.Add(new SharepointDataItem("item 2", "item 2", null, _itemGroups[0]));
            }
            finally
            {
            }
        }

        private async Task loadItemAsync(SharepointDataGroup group)
        {
            var stream = await _connection.RequestAsync("/" + group.UniqueId);
            using (StreamReader reader = new StreamReader(stream))
            {
                var s = await reader.ReadToEndAsync();

                Windows.Web.Syndication.SyndicationFeed feed = new Windows.Web.Syndication.SyndicationFeed();
                feed.Load(s);

                if (feed.Items.Count > 0)
                {
                    var itemGroup=new SharepointDataGroup(feed.Id, feed.Title.NodeValue);
                    _itemGroups.Add(itemGroup);

                    foreach (var item in feed.Items)
                    {
                        itemGroup.Items.Add(
                        new SharepointDataItem(item.Id, item.Title.NodeValue,
                            item.Content == null ? null : item.Content.NodeValue, itemGroup));
                    }
                }
            }
        }

        //private async Task loadItemAsyncJSon(SharepointDataGroup group)
        //{
        //    var stream=await _connection.RequestJsonAsync("/"+group.UniqueId);
        //    Windows.Data.Json.JsonObject json=null;
        //    using (StreamReader reader = new StreamReader(stream))
        //    {
        //        var s = await reader.ReadToEndAsync();
        //        if (s != null)
        //        {
        //            json = Windows.Data.Json.JsonObject.Parse(s);
        //        }
        //    }
        //    if (json != null)
        //    {
        //        var d = json["d"];
        //        if (d != null)
        //        {
        //            var results = d.GetObject()
        //                ["results"].GetArray();
        //            if (results.Count > 0)
        //            {
        //                _itemGroups.Add(group);
        //            }
        //            foreach (var value in results)
        //            {
        //                var values = value.GetObject();

        //                foreach (var o in values)
        //                {
        //                    try
        //                    {
        //                        group.Items.Add(new SharepointDataItem(
        //                            o.Key, values[o.Key].Stringify(), null, group));
        //                    }
        //                    catch (Exception ex)
        //                    {
        //                        System.Diagnostics.Debug.WriteLine("test");
        //                    }
        //                    //var v = values[o.Key].ValueType.ToString();
        //                }
        //            }
                    
        //        }
        //    }
        //}

    }
}